#include <cstdio>
#include <fstream>
#include <cstring>

#include "types.h"
//#include "functions.h"

using namespace std;

// failed to open file, print error information
void OpenFileFailed(const char *filename)
{
	printf("Open file failed: '%s'!\n", filename);
}

// generate outfile name based on infile name and appending string
void formFilename(char **outfile, const char *infile, const char *appstr)
{
	int inlen = strlen(infile);
	int applen = strlen(appstr);
	
	*outfile = new char [inlen + applen + 1];
	strncpy(*outfile, infile, inlen-4);
	strcat(*outfile, appstr);
	strcat(*outfile, ".txt\0");
}

// get a char
char GetChar()
{
	char c, b;
	scanf("%c", &c);
	b = c;
	while (b != '\n')
		scanf("%c", &b);	// clean up the input stream until the end '\n'
	return c;
}

/*****************************************************************************/

// convert a char array(hex) to an unsigned int64 number
void hexstr2uint64(const char *hexstr, uint64 *n)
{
	int len = strlen (hexstr);
	unsigned int tmp;
	
	if (len <= 8)	// number < 2^32
	{
		sscanf(hexstr, "%x", &tmp);
		*n = tmp;
		return;
	}
	// number > 2^32
	char high[9];
	const char *low;
	uint64 hi=0, lo=0;	// int64 & uint64 must be initialized to 0
	
	strncpy(high, hexstr, len - 8);
	high[len - 8] = 0;
	low = hexstr + (len - 8);
	sscanf(high, "%x", &tmp);
	hi = tmp;
	sscanf(low, "%x", &tmp);
	lo = tmp;
	*n = (hi << 32) + lo;
}

// convert an unsigned int64 number to a char array(hex)
void uint642hexstr(const uint64 n, char *str)
{
	unsigned int hi, lo;
	char high[9], low[9];
	hi = (unsigned int)((n >> 32) & 0xffffffff);
	lo = (unsigned int)(n & 0xffffffff);
	sprintf(high, "%x", hi);
	sprintf(low, "%x", lo);
	unsigned int i;
	for (i=0; i<8-strlen(high); ++i)
		str[i] = '0';
	strncpy(str + i, high, strlen(high));
	for (i=0; i<8-strlen(low); ++i)
		str[i+8] = '0';
	strncpy(str + 8 + i, low, strlen(low));
	str[16] = 0;
}

// read all location iterms into a list
void readlocs(ClkLocList *list, const char *filename)
{
	printf(">>> reading location file '%s' ...\n", filename);
	ifstream fin;
	fin.open(filename, ios::in | ios::binary);
	fin.seekg(0, ios::end);
	list->size = fin.tellg() / LOCSIZE;
	assert(fin.tellg() % LOCSIZE == 0);
	list->arr = new ClickLocation [list->size];
	fin.seekg(0, ios::beg);
	fin.read((char *)(list->arr), list->size * LOCSIZE);
	assert(fin.gcount() == (signed)(list->size * LOCSIZE));
	printf(">>> read completed!\n");
}

// use queryID to find the query's first click in click file
// by bin-searching the location iterm in the location list 
int binsearch(const uint64 ID, const ClkLocList *list)
{
	int beg = 0;
	int end = list->size - 1;
	int mid;
	
	while (beg <= end)
	{
		mid = (beg + end) / 2;
		if (list->arr[mid].ID == ID)
			return mid;
		else if (list->arr[mid].ID < ID)
			beg = mid + 1;
		else end = mid - 1;
	}
	return -1;
}
